namespace SimpleWebServices.Web.UI.Html.Validation
{
    using System;
    using System.Xml;
    using SimpleWebServices.Data;
    using SimpleWebServices.Web.UI.Html.Elements;

    public sealed class StandardTextValidator : Validator
    {
        public StandardTextValidator()
            : this(null, 0, 0)
        {
        }

        public StandardTextValidator(IInnerElements display, int minLength, int maxLength)
            : base(display)
        {
            this.MinLength = minLength;
            this.MaxLength = maxLength;
        }

        public int MaxLength
        {
            get;
            set;
        }

        public int MinLength
        {
            get;
            set;
        }

        public override void Configure(IElement element, DataCollection data)
        {
            base.Configure(element, data);

            if (null != data)
            {
                foreach (var datum in data)
                {
                    if ("MaxLength".Equals(datum.Key, StringComparison.OrdinalIgnoreCase))
                    {
                        this.MaxLength = XmlConvert.ToInt32(datum.Value);
                    }
                    else if ("MinLength".Equals(datum.Key, StringComparison.OrdinalIgnoreCase))
                    {
                        this.MinLength = XmlConvert.ToInt32(datum.Value);
                    }
                }
            }
        }

        public override bool Validate(IElement element)
        {
            if (null == element)
            {
                throw new ArgumentNullException("element");
            }

            return this.Validate(element as IControl);
        }

        private bool Validate(IControl control)
        {
            if (null == control)
            {
                throw new ArgumentOutOfRangeException("control");
            }

            return this.Validate(control.Value ?? string.Empty);
        }

        private bool Validate(string value)
        {
            this.Errors.Clear();

            if (0 < this.MinLength && value.Length < this.MinLength)
            {
                this.Errors.Add(new Error(this.ErrorText));
            }
            else if (0 < this.MaxLength && value.Length > this.MaxLength)
            {
                this.Errors.Add(new Error(this.ErrorText));
            }

            return 0 == this.Errors.Count;
        }
    }
}